/**
 * @file shell_port.c
 * @author Letter (NevermindZZT@gmail.com)
 * @brief 
 * @version 0.1
 * @date 2019-02-22
 * 
 * @copyright (c) 2019 Letter
 * 
 */
#include "FreeRTOS.h"
#include "task.h"
#include "shell.h"
#include "common.h"
#include "shell_port.h"
#define TAG "shell_port"
uint8_t switch_window = 0;
Shell shell;
char shellBuffer[256];

static elab_device_t* console;
static elab_device_t* third_device;

static void check_switch_window_shortcut(uint8_t sc);
//static SemaphoreHandle_t shellMutex;

/**
 * @brief 用户shell写
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际写入的数据长度
 */
short userShellWrite(char *data, unsigned short len)
{
    elab_device_write(console, data, len);
    // serialTransmit(&debugSerial, (uint8_t *)data, len, 0x1FF);
    return len;
}


/**
 * @brief 用户shell读
 * 
 * @param data 数据
 * @param len 数据长度
 * 
 * @return short 实际读取到
 */
short userShellRead(char *data, unsigned short len)
{
    bool is_delay[2];
    int ret = elab_device_read(console, data, len);
    is_delay[0] = false;
    if(0 == ret)
    {
        if(elab_device_select(console, 0))
        {
            //do nothing!!
        }
        else
        {
            is_delay[0] = true;
        }
    }

    //检测数据是否需要透传
    char tmp;
    is_delay[1] = false;
    if(elab_device_read(third_device, &tmp, 1) && (THIRD_PARTY_DEVICE1 == switch_window))
    {
        elab_device_write(console, &tmp, 1);
    }
    else
    {
        int res = elab_device_select(third_device, 0);

        if(!res)
        {
            is_delay[1] = true;
        }
    }

    if(is_delay[0] && is_delay[1])
    {
        vTaskDelay(8);
    }
    return ret;
}
#if 0
/**
 * @brief 用户shell上锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellLock(Shell *shell)
{
    xSemaphoreTakeRecursive(shellMutex, portMAX_DELAY);
    return 0;
}

/**
 * @brief 用户shell解锁
 * 
 * @param shell shell
 * 
 * @return int 0
 */
int userShellUnlock(Shell *shell)
{
    xSemaphoreGiveRecursive(shellMutex);
    return 0;
}
#endif

/**
 * @brief shell快捷键
 * 
 * @param shell shell对象
 */
void switch_console_window(Shell *shell)
{
  (void) shell;
    check_switch_window_shortcut(0x17);

}
SHELL_EXPORT_KEY(SHELL_CMD_PERMISSION(0), SWITCH_CONSOLE_WINDOW_KEY_VALUE, switch_console_window, switch console window);


static void check_switch_window_shortcut(uint8_t sc)
{
    if(0x17 == sc)
    {
        // shellClear();
        switch_window = (++switch_window) % MAX_CONSOLE;
        if (LOCAL_CONSOLE == switch_window)
        {
            shellWriteString(&shell, "\r\nOpen terminal window: Third Party Device1.\r\n");
        }
        else if(THIRD_PARTY_DEVICE1 == switch_window)
        {
            shellWriteString(&shell, "\r\nOpen terminal window: Console.\r\n");
        }
    }
}

void shellTask(void *param)
{
    Shell *shell = (Shell *)param;
    char data;
#if SHELL_TASK_WHILE == 1
    while(1)
    {
#endif
        if (shell->read && shell->read(&data, 1) == 1)
        {
            if( LOCAL_CONSOLE == switch_window )
            {
                shellHandler(shell, data);
            }
            else if( THIRD_PARTY_DEVICE1 == switch_window )
            {
                check_switch_window_shortcut(data);
                if( THIRD_PARTY_DEVICE1 == switch_window )
                {
                    elab_device_write(third_device, &data, 1);
                }
            }
        }
#if SHELL_TASK_WHILE == 1
    }
#endif
}

/**
 * @brief 用户shell初始化
 * 
 */

static TaskHandle_t pxCreatedTask;
void userShellInit(void)
{
    console = device_find("console");
    elab_assert(console != NULL);

    third_device = device_find("third_device");
    elab_assert(third_device != NULL);

//    shellMutex = xSemaphoreCreateMutex();

    shell.write = userShellWrite;
    shell.read = userShellRead;
//    shell.lock = userShellLock;
//    shell.unlock = userShellUnlock;
    shellInit(&shell, shellBuffer, sizeof(shellBuffer) / sizeof(shellBuffer[0]));
    if (xTaskCreate(shellTask, "shell", 256+64, &shell, 3, &pxCreatedTask) != pdPASS)
    {
        elog_error("shell task creat failed");
    }
}

INIT_EXPORT(userShellInit, EXPORT_APP);



